
package com.idealighter.game.roomcard.games.mustniuniu.manager;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.idealighter.game.core.assertions.HuohuaAssert;
import com.idealighter.game.core.common.Game;
import com.idealighter.game.games.common.AbstractSeat;
import com.idealighter.game.games.common.SeatState;
import com.idealighter.game.games.common.niuniu.NiuNiuCard;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.player.manager.PlayerMgr;
import com.idealighter.game.player.manager.PlayerMsgWriter;
import com.idealighter.game.player.service.bo.PlayerBo;
import com.idealighter.game.player.struct.Player;
import com.idealighter.game.roomcard.dto.RoomCardMemInfoDto;
import com.idealighter.game.roomcard.games.mustniuniu.constant.MustNiuNiuAdvanceOption;
import com.idealighter.game.roomcard.games.mustniuniu.constant.MustNiuNiuGameState;
import com.idealighter.game.roomcard.games.mustniuniu.convert.ResGameCfgMsgConvert;
import com.idealighter.game.roomcard.games.mustniuniu.convert.ResRoomInfoMsgConvert;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameBillInfo;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameInfo;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameInfo.BetItem;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameInfo.CallDealerItem;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameInfo.MySelfCard;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameInfo.ReadyItem;
import com.idealighter.game.roomcard.games.mustniuniu.dto.GameInfo.ShowCardItem;
import com.idealighter.game.roomcard.games.mustniuniu.dto.RoomInfo;
import com.idealighter.game.roomcard.games.mustniuniu.dto.RoundBillInfo;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResAnswerCloseRoomMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResApplyCloseRoomMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResBetMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResCallDealerMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResChipsChangeMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResChoseDealerMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResCloseRoomCardMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResCloseRoomCardMsg.CloseType;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResCreateRoomCardMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResDealCardsMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResEnterRoomCardMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResExitRoomCardMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResGameCfgMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResGameInfoMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResGameOverMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResGameStartMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResReadyMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResRoundOverMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResSccbFirstDealCardMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResSccbFirstDealCardMsg.FirstDealCardInfo;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResScoreDetailMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResScoreDetailMsg.RoundInfo;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResScoreDetailMsg.ScoreInfo;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResSendMsgMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResShowdownMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResStageMsg;
import com.idealighter.game.roomcard.games.mustniuniu.message.ResTrusteeMsg;
import com.idealighter.game.roomcard.games.mustniuniu.struct.MustNiuNiuRoom;
import com.idealighter.game.roomcard.games.mustniuniu.struct.MustNiuNiuSeat;
import com.idealighter.game.roomcard.games.mustniuniu.struct.MustNiuNiuTable;
import com.idealighter.game.roomcard.struct.gamgcfg.value.NiuNiuRoomCardGameCfgValue;
import com.idealighter.game.roomcard.struct.roomcfg.MustNiuNiuRoomCardRoomCfg;
import com.idealighter.game.roomcard.struct.roomcfg.value.MustNiuNiuRoomCardRoomCfgValue;
import com.idealighter.game.server.db.datadb.generate.domain.RoomCardGroupDomain;
import com.idealighter.game.server.db.datadb.generate.domain.RoomCardNiuniuScoreDetailsDomain;
import com.idealighter.game.server.db.datadb.mapper.RoomCardGroupMapper;
import com.idealighter.utils.check.EmptyUtil;
import com.idealighter.utils.json.JsonUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 四人牛牛消息管理.
 * 
 * @date 2016年1月20日 下午4:46:02
 *
 */
@Singleton
public class MustNiuNiuMsgMgr {
  @Inject
  private PlayerMsgWriter msgWriter;
  @Inject
  private PlayerMgr playerMgr;
  private RoomCardGroupMapper roomCardGroupMapper;

  @Inject
  public MustNiuNiuMsgMgr(RoomCardGroupMapper roomCardGroupMapper) {
    this.roomCardGroupMapper = roomCardGroupMapper;
  }

  /**
   * @Title gameCfgMsg.
   * @Description 返回游戏配置信息
   * @date 2018年6月9日 上午9:05:35
   * @param gameCfgValue .
   * @return .
   */
  public ResGameCfgMsg gameCfgMsg(NiuNiuRoomCardGameCfgValue gameCfgValue) {
    ResGameCfgMsg msg = ResGameCfgMsgConvert.INSTANCE.po2dto(gameCfgValue);
    HuohuaAssert.isTrue(msg != null);
    return msg;
  }

  /**
   * @Title scoreDetailMsg.
   * @Description 战绩详情
   * @author houdongsheng
   * @date 2018年6月14日 上午11:38:15
   * @param player 接收信息的玩家
   * @param detailDomains 战绩详情
   */
  public ResMessage scoreDetailMsg(Player player,
      List<RoomCardNiuniuScoreDetailsDomain> detailDomains) {
    ResScoreDetailMsg msg = new ResScoreDetailMsg();
    int roundStart = Integer.MAX_VALUE;
    int roundEnd = Integer.MIN_VALUE;
    Map<Long, ScoreInfo> scoreInfoMap = new HashMap<Long, ScoreInfo>();

    if (EmptyUtil.listIsEmpty(detailDomains)) {
      roundStart = 0;
      roundEnd = 0;
    } else {
      for (RoomCardNiuniuScoreDetailsDomain item : detailDomains) {
        if (item.getRound() > roundEnd) {
          roundEnd = item.getRound();
        }
        if (item.getRound() < roundStart) {
          roundStart = item.getRound();
        }
        ScoreInfo scoreInfo = scoreInfoMap.get(item.getPlayerId());
        if (scoreInfo == null) {
          scoreInfo = new ScoreInfo();
          scoreInfo.setPlayerId(item.getPlayerId());
          scoreInfo.setSuperId(item.getSuperId());
          scoreInfo.setPlayerName(item.getPlayerName());
          scoreInfo.setAvatar(item.getAvatar());
          scoreInfo.setRounds(new ArrayList<RoundInfo>());
          scoreInfoMap.put(scoreInfo.getPlayerId(), scoreInfo);
        }
        RoundInfo roundInfo = new RoundInfo();
        roundInfo.setRound(item.getRound());
        roundInfo.setBet(item.getBet());
        roundInfo.setScore(item.getScore());
        roundInfo.setTotalScore(item.getTotalScore());
        roundInfo.setCardsType(item.getCardType().intValue());
        roundInfo.setCards(JsonUtil.fromJsonToList(item.getCardValues(), Integer.class));
        roundInfo.setIsBanker(item.getIsBanker() ? 1 : 0);
        roundInfo.setCallBankerMultiple(item.getCallBankerMultiple());
        roundInfo.setBetOtherPlayerId(item.getBetOtherPlayerId());
        roundInfo.setBetOtherPlayerName(item.getBetOtherPlayerName());
        roundInfo.setBetOtherChips(item.getBetOtherChips());
        scoreInfo.getRounds().add(roundInfo);
      }
    }
    List<ScoreInfo> details = new ArrayList<>(scoreInfoMap.values());
    if (EmptyUtil.listIsNotEmpty(details)) {
      for (ScoreInfo item : details) {
        // 升序排列
        Collections.sort(item.getRounds(), (a, b) -> a.getRound() - b.getRound());
      }
    }
    msg.setRoundStart(roundStart);
    msg.setRoundEnd(roundEnd);
    msg.setDetails(details);
    return msg;
  }

  /**
   * @Title sendGameStage.
   * @Description 发送游戏阶段信息
   * @date 2018年6月9日 上午9:04:57
   * @param table .
   * @param time .
   */
  public void sendGameStage(MustNiuNiuTable table, int time) {
    ResStageMsg msg = new ResStageMsg();
    msg.setTime(time);
    msg.setState(table.getStatus().val);
    sendTablePlayersMsg(table, msg);
  }

  /**
   * @Title sendDealSccbFirstFourCardsMsg.
   * @Description 发前四张牌
   * @date 2018年6月9日 上午9:04:35
   * @param table .
   */
  public void sendDealSccbFirstFourCardsMsg(MustNiuNiuTable table) {
    // 判断是否为暗抢庄家
    boolean blindCallBanker =
        table.findAdvanceOptionPo(MustNiuNiuAdvanceOption.BLIND_CALL_BANKER) != null;
    for (MustNiuNiuSeat seat : table.seats()) {
      if (seat.getPlayerId() == 0) {
        continue;
      }
      ResSccbFirstDealCardMsg msg = new ResSccbFirstDealCardMsg();
      List<FirstDealCardInfo> cardInfos = new ArrayList<FirstDealCardInfo>();
      for (MustNiuNiuSeat item : table.getGameSeats(true)) {
        if (item.readied()) {
          FirstDealCardInfo cardInfo = new FirstDealCardInfo();
          cardInfo.setOrder(item.getOrder());
          cardInfo.setPlayerId(item.getPlayerId());
          // 暗抢庄家时，看不到别人的牌
          if (!(blindCallBanker && item.getPlayerId() != seat.getPlayerId())) {
            List<NiuNiuCard> cards = item.getCards();
            for (NiuNiuCard card : cards) {
              cardInfo.getCards().add(card.ordinal());
            }
          }
          cardInfos.add(cardInfo);
        }
      }
      msg.setCardInfos(cardInfos);
      System.out.println("发送四张牌消息： " + JsonUtil.toJson(msg));
      // 给所有玩家发送一份数据（包括旁观者玩家）
      msgWriter.writeMsg(seat.getPlayerId(), msg);
    }
  }


  public void sendGameStartMsg(MustNiuNiuTable table) {
    ResGameStartMsg msg = new ResGameStartMsg();
    sendTablePlayersMsg(table, msg);
  }

  /**
   * @Title sendReadyMsg.
   * @Description 发送准备通知
   * @date 2018年6月8日 下午8:32:01
   * @param seat .
   */
  public void sendReadyMsg(MustNiuNiuSeat seat) {
    ResReadyMsg msg = new ResReadyMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.getTable(), msg);
  }

  /**
   * @Title sendExitRoomCardMsg.
   * @Description 发送退出房间通知
   * @date 2018年6月8日 下午8:33:34
   * @param seat .
   */
  public void sendExitRoomCardMsg(MustNiuNiuSeat seat) {
    ResExitRoomCardMsg msg = new ResExitRoomCardMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.getTable(), msg);
  }

  /**
   * 发送座位叫庄消息.
   * 
   * @param seat 座位信息.
   * @param multiple . 0:不叫,非0叫庄倍数
   */
  public void sendCallDealerMsg(MustNiuNiuSeat seat, int multiple) {
    ResCallDealerMsg msg = new ResCallDealerMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setOrder(seat.getOrder());
    msg.setMultiple(multiple);
    // 判断是否为暗抢庄家
    boolean blindCallBanker =
        seat.table().findAdvanceOptionPo(MustNiuNiuAdvanceOption.BLIND_CALL_BANKER) != null;
    if (blindCallBanker) {
      msgWriter.writeMsg(seat.getPlayerId(), msg);
    } else {
      sendTablePlayersMsg(seat.getTable(), msg);
    }
  }

  /**
   * @Title sendDealBankerMsg.
   * @Description 发送确认庄家消息
   * @date 2018年6月4日 上午9:45:38
   * @param bankerSeat .
   */
  public void sendDealBankerMsg(MustNiuNiuSeat bankerSeat) {
    ResChoseDealerMsg msg = new ResChoseDealerMsg();
    msg.setOrder(bankerSeat.order);
    msg.setPlayerId(bankerSeat.getPlayerId());
    msg.setMultiple(bankerSeat.getCallDealerMultiple());
    sendTablePlayersMsg(bankerSeat.getTable(), msg);
  }

  /**
   * @Title sendBetMsg.
   * @Description 发送下注信息
   * @author houdongsheng
   * @date 2018年6月4日 上午11:40:37
   * @param seat 玩家座位
   * @param betOther 是否买码
   */
  public void sendBetMsg(MustNiuNiuSeat seat, boolean betOther) {
    ResBetMsg msg = new ResBetMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    if (betOther) { // 买码
      msg.setChips(seat.getBetOtherBetChips());
      msg.setOtherPlayerId(seat.getBetOtherPlayerId());
    } else { // 下自己
      msg.setChips(seat.getBetedchips());
    }

    sendTablePlayersMsg(seat.getTable(), msg);
  }

  /**
   * @Title sendDealCardsMsg.
   * @Description 给玩家发牌通知
   * @date 2018年6月5日 上午10:38:59
   * @param seat .
   */
  public void sendDealCardsMsg(MustNiuNiuSeat seat) {
    ResDealCardsMsg msg = new ResDealCardsMsg();
    msg.setCardsType(seat.getCardsType().niu);
    for (NiuNiuCard card : seat.getCards()) {
      msg.getCards().add(card.ordinal());
    }
    for (NiuNiuCard card : seat.getBestCards()) {
      msg.getBestCards().add(card.ordinal());
    }
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * @Title sendShowdownMsg.
   * @Description 摊牌消息
   * @author houdongsheng
   * @date 2018年6月5日 下午2:43:38
   * @param seat .
   */
  public void sendShowdownMsg(MustNiuNiuSeat seat) {
    ResShowdownMsg msg = new ResShowdownMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setOrder(seat.getOrder());
    seat.getBestCards().forEach(card -> msg.getCards().add(card.ordinal()));
    msg.setCardsType(seat.getCardsType().niu);
    sendTablePlayersMsg(seat.getTable(), msg);
  }

  /**
   * @Title sendTrusteeChangeMsg.
   * @Description 发送托管变化消息
   * @date 2018年6月9日 上午9:08:07
   * @param seat .
   * @param trustee 是否托管
   */
  public void sendTrusteeChangeMsg(MustNiuNiuSeat seat, boolean trustee) {
    ResTrusteeMsg msg = new ResTrusteeMsg();
    msg.setOrder(seat.order);
    msg.setPlayerId(seat.getPlayerId());
    msg.setTrustee(trustee ? 1 : 0);
    sendTablePlayersMsg(seat.getTable(), msg);
  }

  /**
   * @Title sendChipsChangeMsg.
   * @Description 发送筹码变化
   * @date 2018年6月5日 下午3:26:18
   * @param seat .
   */
  public void sendChipsChangeMsg(MustNiuNiuSeat seat) {
    ResChipsChangeMsg msg = new ResChipsChangeMsg();
    msg.setChips(seat.getTotalChips());
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.getTable(), msg);
  }

  /**
   * @Title sendCloseRoomCardMsg.
   * @Description 发送关闭房间消息
   * @date 2018年6月9日 上午9:03:46
   * @param table .
   * @param type .
   */
  public void sendCloseRoomCardMsg(MustNiuNiuTable table, CloseType type) {
    ResCloseRoomCardMsg msg = new ResCloseRoomCardMsg();
    msg.setType(type.type);
    sendTablePlayersMsg(table, msg);
  }

  /**
   * @Title sendApplyCloseRoomCardMsg.
   * @Description 发送申请关闭房间
   * @date 2018年6月8日 下午4:13:22
   * @param seat 座位
   * @param time 应答时间
   */
  public void sendApplyCloseRoomCardMsg(MustNiuNiuSeat seat, int time) {
    ResApplyCloseRoomMsg msg = new ResApplyCloseRoomMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    msg.setTime(time);
    sendTablePlayersMsg(seat.table(), msg);
  }

  /**
   * @Title sendAnswerApplyCloseRoomMsg.
   * @Description 应答关闭房间通知
   * @date 2018年6月8日 下午7:53:22
   * @param seat .
   */
  public void sendAnswerApplyCloseRoomMsg(MustNiuNiuSeat seat) {
    ResAnswerCloseRoomMsg msg = new ResAnswerCloseRoomMsg();
    msg.setAgree(seat.getAnswerCloseRoom() ? 1 : 0);
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table(), msg);
  }

  /**
   * @Title sendRoundOver.
   * @Description 发送本局结算通知
   * @date 2018年6月8日 下午7:53:47
   * @param table .
   * @param billInfos .
   */
  public void sendRoundOver(MustNiuNiuTable table, List<RoundBillInfo> billInfos) {
    ResRoundOverMsg msg = new ResRoundOverMsg();
    msg.setBillInfos(billInfos);
    sendTablePlayersMsg(table, msg);
  }

  /**
   * @Title sendGameOver.
   * @Description 发送游戏结束
   * @date 2018年6月8日 下午5:47:34
   * @param table .
   * @param billInfos .
   */
  public void sendGameOver(MustNiuNiuTable table, List<GameBillInfo> billInfos) {
    ResGameOverMsg msg = new ResGameOverMsg();
    msg.setStage(table.getStatus().val);
    msg.setBillInfos(billInfos);
    sendTablePlayersMsg(table, msg);
  }

  /**
   * 发送最新信息.
   *
   * @Title sendGameLastInfo.
   * @param seat 位置.
   * @return 消息.
   */
  public ResMessage gameLastInfo(MustNiuNiuSeat seat) {
    ResGameInfoMsg msg = new ResGameInfoMsg();
    MustNiuNiuRoom room = seat.getTable().room();
    List<RoomCardMemInfoDto> mems = new ArrayList<>();
    MustNiuNiuTable table = seat.table();
    for (Long playerId : table.players()) {
      RoomCardMemInfoDto memInfo = room.memInfo(playerId);
      // 只发送已经坐下的用户和自己信息
      if (memInfo.getPlayerId() == seat.getPlayerId() || memInfo.getByStander() == 0) {
        mems.add(memInfo);
      }
    }
    msg.setMems(mems);
    msg.setRoom(toRoomInfo(table.room()));
    msg.setGameInfo(toGameInfo(seat));
    return msg;
  }

  /**
   * @Title createRoomCardMsg.
   * @Description 返回创建房间消息
   * @date 2018年6月9日 上午9:02:05
   * @param roomId .
   * @return .
   */
  public ResCreateRoomCardMsg createRoomCardMsg(long roomId) {
    ResCreateRoomCardMsg msg = new ResCreateRoomCardMsg();
    msg.setRoomId(roomId);
    return msg;
  }


  private GameInfo toGameInfo(MustNiuNiuSeat mySeat) {
    MustNiuNiuTable table = mySeat.getTable();
    GameInfo result = new GameInfo();
    // 游戏状态
    result.setStage(gameStage(table));
    // 本状态剩余时间
    int stageTime = 0;
    if (result.getStage() != MustNiuNiuGameState.NO_START.val) {
      stageTime = (int) table.stepFuture.getDelay(TimeUnit.SECONDS);
    }
    result.setStageTime(stageTime);
    // 可推注选项
    result.setPreWinBetSelf(mySeat.getPreWinBetSelf());

    List<ReadyItem> readyList = new ArrayList<ReadyItem>(); // 准备列表
    List<CallDealerItem> callDealerList = new ArrayList<CallDealerItem>(); // 叫庄列表
    Long dealer = 0L; // 庄家编号
    int dealerCallDealerMultiple = 0; // 庄家抢庄倍数
    List<BetItem> betList = new ArrayList<BetItem>(); // 下注列表
    MySelfCard mySelfCard = null; // 我的牌
    List<ShowCardItem> showCardList = new ArrayList<ShowCardItem>(); // 摊牌列表
    List<RoundBillInfo> billInfos = new ArrayList<>(); // 本局结算信息
    // 是否为明牌抢庄
    boolean blindCallBanker =
        table.findAdvanceOptionPo(MustNiuNiuAdvanceOption.BLIND_CALL_BANKER) != null;

    List<MustNiuNiuSeat> seats = table.getGameSeats(true);
    for (MustNiuNiuSeat seat : seats) {
      // 准备情况
      ReadyItem readyItem = new ReadyItem();
      readyItem.setOrder(seat.getOrder());
      readyItem.setPlayerId(seat.getPlayerId());
      readyItem.setReady(seat.readied() ? 1 : 0);
      readyList.add(readyItem);

      // 叫庄情况
      if (blindCallBanker) { // 暗抢庄家，只限制自己的抢庄情况
        if (seat.getPlayerId() == mySeat.getPlayerId()) {
          CallDealerItem callDealerItem = new CallDealerItem();
          callDealerItem.setOrder(seat.getOrder());
          callDealerItem.setPlayerId(seat.getPlayerId());
          Integer callDealerMultiple = seat.getCallDealerMultiple();
          callDealerItem.setMultiple(callDealerMultiple == null ? -1 : callDealerMultiple);
          callDealerList.add(callDealerItem);
        }
      } else { // 非暗抢庄家,显示所有人的抢庄情况
        CallDealerItem callDealerItem = new CallDealerItem();
        callDealerItem.setOrder(seat.getOrder());
        callDealerItem.setPlayerId(seat.getPlayerId());
        Integer callDealerMultiple = seat.getCallDealerMultiple();
        callDealerItem.setMultiple(callDealerMultiple == null ? -1 : callDealerMultiple);
        callDealerList.add(callDealerItem);
      }


      // 庄家
      if (seat.isDealer()) {
        dealer = seat.getPlayerId();
        dealerCallDealerMultiple = seat.getCallDealerMultiple();
      }

      // 我自己的牌
      if (seat.getPlayerId() == mySeat.getPlayerId()) {
        mySelfCard = new MySelfCard();
        mySelfCard.setOrder(seat.getOrder());
        for (NiuNiuCard card : seat.getCards()) {
          mySelfCard.getCards().add(card.ordinal());
        }
        if (seat.getCards().size() == 5) {
          mySelfCard.setCardsType(seat.getCardsType().niu);
          List<Integer> bestCards = new ArrayList<Integer>();
          for (NiuNiuCard card : seat.getBestCards()) {
            bestCards.add(card.ordinal());
          }
          mySelfCard.setBestCards(bestCards);
        }
      }

      // 下注情况
      BetItem betItem = new BetItem();
      betItem.setPlayerId(seat.getPlayerId());
      betItem.setOrder(seat.getOrder());
      betItem.setChips(seat.getBetedchips());
      Long betOtherPlayerId = seat.getBetOtherPlayerId();
      if (betOtherPlayerId == null) {
        betItem.setBetOtherPlayerId(-1L);
        betItem.setBetOtherChips(0L);
      } else if (betOtherPlayerId.equals(0L)) {
        betItem.setBetOtherPlayerId(0L);
        betItem.setBetOtherChips(0L);
      } else {
        betItem.setBetOtherPlayerId(seat.getBetOtherPlayerId());
        betItem.setBetOtherChips(seat.getBetedchips());
      }
      betList.add(betItem);

      // 摊牌列表
      ShowCardItem showCardItem = new ShowCardItem();
      showCardItem = new ShowCardItem();
      showCardItem.setPlayerId(seat.getPlayerId());
      showCardItem.setOrder(seat.getOrder());
      showCardItem.setShow(seat.isShowdown() ? 1 : 0);
      // 如果是明牌抢庄,且非暗抢庄家,且未摊牌
      if (table.isShowCardCallBanker()) { // 如果是明牌抢庄
        if (seat.readied()) {
          List<NiuNiuCard> cards = null;
          if (blindCallBanker) { // 暗抢庄家
            if (seat.getPlayerId() == mySeat.getPlayerId()) { // 自己的牌，显示全部
              if (seat.isShowdown()) {
                cards = seat.getBestCards().subList(0, seat.getCards().size());
              } else {
                cards = seat.getCards().subList(0, seat.getCards().size());
              }
            } else { // 别人的牌，当已经摊牌，显示全部，否则不显示
              if (seat.isShowdown()) {
                cards = seat.getBestCards().subList(0, seat.getCards().size());
              }
            }
          } else { // 非暗抢庄家
            if (!seat.isShowdown() && (seat.getPlayerId() != mySeat.getPlayerId())) { // 未亮牌的其他人
              if (table.getStatus().equals(MustNiuNiuGameState.OPEN_CARD)) { // 等待亮牌阶段,需要少显示一张牌
                cards = seat.getCards().subList(0, seat.getCards().size() - 1);
              } else {
                cards = seat.getCards().subList(0, seat.getCards().size());
              }
            } else if (seat.isShowdown()) { // 已经亮牌
              cards = seat.getBestCards().subList(0, seat.getCards().size());
            } else if (seat.getPlayerId() == mySeat.getPlayerId()) { // 自己未亮牌
              cards = seat.getCards().subList(0, seat.getCards().size());
            }
          }
          if (EmptyUtil.listIsNotEmpty(cards)) {
            for (NiuNiuCard card : cards) {
              showCardItem.getCards().add(card.ordinal());
            }
          }
        }
      } else { // 其余游戏
        if (seat.isShowdown()) {
          List<NiuNiuCard> cards = seat.getBestCards().subList(0, seat.getCards().size());
          for (NiuNiuCard card : cards) {
            showCardItem.getCards().add(card.ordinal());
          }
        } else {
          if (seat.getPlayerId() == mySeat.getPlayerId()) { // 我自己的牌
            List<NiuNiuCard> cards = seat.getCards().subList(0, seat.getCards().size());
            for (NiuNiuCard card : cards) {
              showCardItem.getCards().add(card.ordinal());
            }
          }
        }
      }

      if (seat.getCardsType() != null) {
        showCardItem.setCardsType(seat.getCardsType().niu);
      }
      showCardList.add(showCardItem);

      // 在展示结果阶段,发送结算信息
      if (table.getStatus().equals(MustNiuNiuGameState.SHOW_RESULT)) {
        if (seat.getState().equals(SeatState.GAMING)) {
          long playerId = seat.getPlayerId();
          RoundBillInfo billInfo = new RoundBillInfo();
          billInfo.setOrder(seat.getOrder());
          billInfo.setChips(seat.getBillChips());
          billInfo.setPlayerId(playerId);
          billInfo.setPreWinBetSelf(seat.getPreWinBetSelf());
          billInfos.add(billInfo);
        }
      }
    }

    result.setReadyList(readyList);
    result.setCallDealerList(callDealerList);
    result.setDealer(dealer);
    result.setCallDealerMultiple(dealerCallDealerMultiple);
    result.setBetList(betList);
    result.setShowCardList(showCardList);
    result.setBillInfos(billInfos);

    result.setMySelfCard(mySelfCard);
    return result;
  }

  private int gameStage(MustNiuNiuTable table) {
    return table.getStatus().val;
  }

  private RoomInfo toRoomInfo(MustNiuNiuRoom room) {
    MustNiuNiuRoomCardRoomCfg roomDom = room.getRoomCfg();
    long ownerId = room.getOwnerId();
    PlayerBo owner = playerMgr.selectPlayer(ownerId);
    int groupId = roomDom.getGroupId();

    String groupName = "";
    if (groupId > 0) {
      RoomCardGroupDomain groupDomain = roomCardGroupMapper.selectByPrimaryKey(groupId);
      groupName = groupDomain.getGroupName();
    }
    Game game = room.game();

    int totalRound = roomDom.getPlayGames() + roomDom.getLeftGame();
    int curRound = roomDom.getPlayGames();
    MustNiuNiuRoomCardRoomCfgValue cfgValue = roomDom.cfgs();
    RoomInfo roomInfo = ResRoomInfoMsgConvert.INSTANCE.po2dto(roomDom.getId(), ownerId,
        owner.getSuperId(), owner.getPlayerName(), groupId, groupName, game.getType(),
        game.getDesc(), roomDom.getPayBy().intValue(), roomDom.getPrice(), cfgValue, curRound,
        totalRound, roomDom.getCreateTime().getTime());

    return roomInfo;
  }

  /**
   * @Title sendEnterRoomCardMsg.
   * @Description 发送进入房卡信息
   * @date 2018年6月1日 下午8:51:50
   * @param player .
   */
  public void sendEnterRoomCardMsg(Player player) {
    ResEnterRoomCardMsg msg = new ResEnterRoomCardMsg();

    MustNiuNiuRoom room = player.curSeat.table().room();
    RoomCardMemInfoDto memInfo = room.memInfo(player.playerBo().getId());
    msg.setMem(memInfo);

    sendTablePlayersMsg(player.curSeat.table(), msg);
  }

  /**
   * @Title sendMsgMsg.
   * @Description 聊天
   * @author houdongsheng
   * @date 2018年6月8日 上午11:26:30
   * @param player .
   * @param otherPlayerId 其他玩家
   * @param otherOrder 接收玩家座位号
   * @param msgType 消息类型
   * @param content 消息内容
   */
  public void sendMsgMsg(Player player, long otherPlayerId, int otherOrder, int msgType,
      String content) {
    ResSendMsgMsg msg = new ResSendMsgMsg();
    msg.setOrder(player.curSeat.getOrder());
    msg.setPlayerId(player.getId());
    msg.setOtherOrder(otherOrder);
    msg.setOtherPlayerId(otherPlayerId);
    msg.setMsgType(msgType);
    msg.setMsg(content);


    sendTablePlayersMsg(player.curSeat.table(), msg);

  }
  // =======================

  /**
   * 向同桌的玩家(包括自己)发送消息.
   * 
   * @param table .
   * @param msg .
   */
  public void sendTablePlayersMsg(MustNiuNiuTable table, ResMessage msg) {
    List<? extends AbstractSeat> seats = table.seats();
    for (int i = 0; i < seats.size(); i++) {
      AbstractSeat seat = seats.get(i);
      long playerId = seat.getPlayerId();
      if (playerId > 0) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 向同房间的玩家(包括自己)发送消息.
   * 
   * @param room .
   * @param msg .
   */
  public void sendRoomPlayersMsg(MustNiuNiuRoom room, ResMessage msg) {
    room.getPlayers().forEach(p -> msgWriter.writeMsg(p, msg));
  }
}
